﻿using System;

namespace Notoric.Commanding.Holders
{
    /// <summary>
    /// Base interface for value holders used for command parameters.
    /// </summary>
    /// <remarks>
    /// <para>
    /// In order to support binding of command paramters to the values computed by other commands in a way
    /// that is transparent for the executing command, value holders are used in place of simple values.
    /// </para>
    /// <para>
    /// The value of the value holder can be in one of the following states:
    /// <list type="bullet">
    /// <item><see cref="F:Notoric.Commanding.Holders.ValueState.Computed"/> meaning that the value is known an can be directly used</item>
    /// <item><see cref="F:Notoric.Commanding.Holders.ValueState.Unknown"/> meaning that the value is not known at the moment</item>
    /// </list>
    /// </para>
    /// </remarks>
    public interface IValueHolder
    {
        /// <summary>
        /// Resets the <see cref="P:Notoric.Commanding.Holders.IValueHolder.ValueState"/> property to the 
        /// <see cref="F:Notoric.Commanding.Holders.ValueState.Unknown"/> state.
        /// </summary>
        void UnsetValue();

        /// <summary>
        /// Gets or sets the value that this holder holds.
        /// </summary>
        /// <value>
        /// <para>
        /// The value held by this holder. Setting the value automatically forces a transition to the <see cref="F:Notoric.Commanding.Holders.ValueState.Computed"/> state.
        /// </para>
        /// </value>
        /// <exception cref="ValueNotKnownException">
        /// The value is not known 
        /// (The <see cref="P:Notoric.Commanding.Holders.IValueHolder.ValueState"/> property equals to <see cref="F:Notoric.Commanding.Holders.ValueState.Unknown"/>).
        /// </exception>
        object WrappedValue
        {
            get;
            set;
        }

        /// <summary>
        /// Gets the value state.
        /// </summary>
        /// <value>
        /// <para>
        /// One of the <see cref="Notoric.Commanding.Holders.ValueState"/> values.
        /// </para>
        /// </value>
        ValueState ValueState
        {
            get;
        }

        /// <summary>
        /// Gets the type of the value held by this holder.
        /// </summary>
        Type ValueType
        {
            get;
        }
    }

    /// <summary>
    /// Determines the state of the value held by a <see cref="IValueHolder"/>.
    /// </summary>
    public enum ValueState
    {
        /// <summary>
        /// The value held by the holder is not known.
        /// </summary>
        Unknown,
        /// <summary>
        /// The value held by the holder is known and can be used directly.
        /// </summary>
        Computed
    }
}
